﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
using System.IO.IsolatedStorage;
using System.Security.Cryptography;
using System.IO;
using System.Xml.Serialization;

namespace CodeStash.Addin.Core
{
    /// <summary>
    /// Manage the client credentials in isolated storage which will be used in all calls to the
    /// server.
    /// </summary>
    public static class CredentialManager
    {
        private const string FileName = "Code.stash";
        private const string iv = "63D4B63D";
        private const string key = "863E9F61";

        /// <summary>
        /// Save the email and password.
        /// </summary>
        /// <param name="login">The user details to save.</param>
        [Obsolete]
        public static void Save(LoginDetails login)
        {
            login.Validate();

            XmlSerializer serializer = new XmlSerializer(typeof(LoginDetails));
            using (StringWriter sw = new StringWriter())
            {
                serializer.Serialize(sw, login);
                SaveFile(ASCIIEncoding.ASCII.GetBytes(sw.ToString()));
            }
        }

        /// <summary>
        /// Load the login details.
        /// </summary>
        /// <returns>The user login information to be used in the website calls.</returns>
        [Obsolete]
        public static LoginDetails Load()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(LoginDetails));
            string fileContents = ReadFile();
            if (!string.IsNullOrWhiteSpace(fileContents))
            {
                using (StringReader sr = new StringReader(fileContents))
                {
                    return (LoginDetails)serializer.Deserialize(sr);
                }
            }
            // If we get here, we haven't previously created the file.
            return new LoginDetails();
        }

        /// <summary>
        /// Reset the file by removing it.
        /// </summary>
        [Obsolete]
        public static void Reset()
        {
            using (IsolatedStorageFile store = GetStore())
            {
                if (store.FileExists(FileName))
                {
                    store.DeleteFile(FileName);
                }
            }
        }

        private static void SaveFile(byte[] fileData)
        {
            using (IsolatedStorageFile store = GetStore())
            {
                using (IsolatedStorageFileStream ifs = GetStream(store, FileMode.OpenOrCreate))
                {
                    using (DESCryptoServiceProvider des = GetCryptoProvider())
                    {
                        using (CryptoStream crypt = new CryptoStream(ifs, des.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            crypt.Write(fileData, 0, fileData.Length);
                            crypt.Close();
                        }
                    }
                }
            }
        }

        private static string ReadFile()
        {
            using (IsolatedStorageFile store = GetStore())
            {
                if (!store.FileExists(FileName))
                {
                    return string.Empty;
                }

                using (IsolatedStorageFileStream ifs = GetStream(store, FileMode.Open))
                {
                    using (DESCryptoServiceProvider des = GetCryptoProvider())
                    {
                        using (CryptoStream crypt = new CryptoStream(ifs, des.CreateDecryptor(), CryptoStreamMode.Read))
                        {
                            using (StreamReader reader = new StreamReader(crypt))
                            {
                                string retVal = reader.ReadToEnd();
                                crypt.Close();

                                return retVal;
                            }
                        }
                    }
                }
            }
        }

        private static IsolatedStorageFile GetStore()
        {
            IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForDomain();
            return isoFile;
        }

        private static IsolatedStorageFileStream GetStream(IsolatedStorageFile file, FileMode mode)
        {
            IsolatedStorageFileStream ifs = new IsolatedStorageFileStream(FileName, mode, file);
            return ifs;
        }

        private static DESCryptoServiceProvider GetCryptoProvider()
        {
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
            provider.Key = ASCIIEncoding.ASCII.GetBytes(key);
            provider.IV = ASCIIEncoding.ASCII.GetBytes(iv);

            return provider;
        }
    }
}